www.gusucode.com > VC++ 实现图像中的文字提取-源码程序 > VC++ 实现图像中的文字提取-源码程序/code/图像中文字提取的程序/ImageAnalysis.cpp
//Download by http://www.NewXing.com #include "stdafx.h" #include "GlobalApi.h" #include "Cdib.h" #include <io.h> #include <errno.h> #include <math.h> #include <direct.h> /* 说明: 该函数将消去图象中面积小于或大于阈值的区域,实现文字提取*/ BOOL DIBHOLENUMBER(CDib *pDib) { // 指向源图像的指针 BYTE * lpSrc; //图象的宽度和高度 LONG lWidth; LONG lHeight; // 图像每行的字节数 LONG lLineBytes; //得到图象的宽度和高度 CSize SizeDim; SizeDim = pDib->GetDimensions(); lWidth = SizeDim.cx; lHeight = SizeDim.cy; //得到实际的Dib图象存储大小 CSize SizeRealDim; SizeRealDim = pDib->GetDibSaveDim(); // 计算图像每行的字节数 lLineBytes = SizeRealDim.cx; //图像数据的指针 LPBYTE lpDIBBits = pDib->m_lpImage; // 循环变量 int i, j, s, n; // 空穴的数目以及面积阈值 int nHoleNum, nMinArea,nMaxArea; int nBlackPix, temp; // 正向和反响传播标志 int nDir1,nDir2; // 用来存储的一位数组 int *pnBinary; pnBinary =new int[lHeight*lLineBytes]; // 定义阈值的大小 nMinArea = 130; nMaxArea = 700; // 将图象二值化 for (j = 0; j < lHeight; j++) { for(i = 0; i < lWidth; i++) { // 指向源图像倒数第j行,第i个象素的指针 lpSrc = (unsigned char *)lpDIBBits + lLineBytes * j + i; // 白色象素为背景,存成0 if(*lpSrc > 200) { pnBinary[lLineBytes * j + i] = 0; } // 黑象素存成-1 else { pnBinary[lLineBytes * j + i] = -1; } } } // 空穴数赋初值 nHoleNum = 1; do { s=0; // 寻找每个空穴的初始象素值 for (j = 1; j < lHeight - 1; j++) { for(i = 1; i < lWidth - 1; i++) { // 找到初始象素 if(pnBinary[lLineBytes * j + i] == -1) { s = 1; // 将象素值改成当前的空穴数值 pnBinary[lLineBytes * j + i] = nHoleNum; // 跳出循环 j = lHeight; i = lLineBytes; } } } //没有初始象素,跳出循环 if(s == 0) break; else { do { // 正向和反响系数赋初值0 nDir1 = 0; nDir2 = 0; // 正向扫描 for (j = 1; j < lHeight-1; j++) { for(i = 1; i < lWidth-1; i++) { nBlackPix = pnBinary[lLineBytes * j + i]; // 如果象素已经被扫描,或者是背景色,进行下一个循环 if(nBlackPix != -1) continue; // 如果上侧或者左侧的象素值已经被扫描,且属于当前的空穴,当前的象素值 // 改成空穴的数值 nBlackPix=pnBinary[lLineBytes * (j-1) + i]; if(nBlackPix == nHoleNum) { pnBinary[lLineBytes * j + i] = nHoleNum; nDir1 = 1; continue; } nBlackPix =pnBinary[lLineBytes * j + i - 1]; if(nBlackPix == nHoleNum) { pnBinary[lLineBytes * j + i] = nHoleNum; nDir1 = 1; } } } // 正向象素全部被扫描,跳出循环 if(nDir1 == 0) break; // 反向扫描 for (j = lHeight-2; j >= 1 ; j--) { for(i = lWidth-2; i >= 1 ; i--) { nBlackPix = pnBinary[lLineBytes * j + i]; // 如果象素已经被扫描,或者是背景色,进行下一个循环 if(nBlackPix != -1) continue; // 如果下侧或者右侧的象素值已经被扫描,且属于当前的空穴,当前的象素值 // 改成空穴的数值 nBlackPix=pnBinary[lLineBytes * (j+1) + i]; if(nBlackPix == nHoleNum) { pnBinary[lLineBytes * j + i] = nHoleNum; nDir2 = 1; continue; } nBlackPix =pnBinary[lLineBytes * j + i + 1]; if(nBlackPix == nHoleNum) { pnBinary[lLineBytes * j + i] = nHoleNum; nDir2 = 1; } } } if(nDir2 == 0) break; } while(1); } // 空穴数增加 nHoleNum++; } while(1); nHoleNum -- ; // 寻找面积小于或大于阈值的区域 for(n = 1; n <= nHoleNum; n++) { s = 0; for (j = 0; j < lHeight - 1; j++) { for(i = 0; i < lWidth - 1; i++) { nBlackPix =pnBinary[lLineBytes * j + i]; if(nBlackPix == n) s++; } } // 小于或大于阈值的区域,赋以与背景一样的颜色,进行消去 if((s <= nMinArea)||(s > nMaxArea)) { for (j = 0; j < lHeight - 1; j++) { for(i = 0; i < lWidth - 1; i++) { nBlackPix =pnBinary[lLineBytes * j + i + 1]; if(nBlackPix == n) { pnBinary[lLineBytes * j + i + 1] = 0; } } } } } // 存储象素值,输出 for(j = 0; j < lHeight; j++) { // 列 for(i = 0; i < lWidth; i++) { // 二值图象 temp = pnBinary[j * lLineBytes + i] ; // 指向位图i行j列象素的指针 lpSrc = (unsigned char*)lpDIBBits + lLineBytes * j + i; // 更新源图像 if(temp != 0) * (lpSrc) = 0; else * (lpSrc) = 255; } } delete pnBinary; return true; }